#include "decoder/frame_decoder.hpp"
#include <iostream>
#include <cstring>

namespace WD {

// 构造函数
// 构造函数
FrameDecoder::FrameDecoder(const std::string& url,const int max_streams)
                    : input_url_(url) 
                    , max_streams_(max_streams)
{
    avformat_network_init();
}

FrameDecoder::~FrameDecoder() {

}

///TODO: 优化 为workers_中每一个worker设置一个setFrameCallback回调函数
void FrameDecoder::setStitchedFrameCallback(const FrameCallback& cb) {
    stitched_frame_cb_ = cb;
}

void FrameDecoder::setStreamCallback(int stream_index, const FrameCallback& cb) {
    stream_callbacks_[stream_index] = cb;
}

void FrameDecoder::setSubtitleCallback(const SubtitleCallback& cb) {
    subtitle_cb_ = cb;
}

void FrameDecoder::start() {
    if (avformat_open_input(&fmt_ctx_, input_url_.c_str(), nullptr, nullptr) < 0) {
        throw std::runtime_error("Failed to open input");
    }
    if (avformat_find_stream_info(fmt_ctx_, nullptr) < 0) {
        throw std::runtime_error("Failed to find stream info");
    }

    for (unsigned int i = 0; i <= max_streams_; ++i) {
        AVCodecParameters* codecpar = fmt_ctx_->streams[i]->codecpar;

        auto pkt_queue = std::make_shared<ThreadSafeQueue<AVPacket*>>();
        pkt_queues_[i] = pkt_queue;

        if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            // 判断是否是拼接流（单路）模式
            FrameCallback cb;
            if (max_streams_ == 1 && stitched_frame_cb_) {
                cb = stitched_frame_cb_;
            } else if (stream_callbacks_.count(i)) {
                cb = stream_callbacks_[i];
            } else {
                throw std::runtime_error("No callback provided for stream " + std::to_string(i));
            }
            auto worker = std::make_unique<StreamDecoderWorker>(
                i, fmt_ctx_, codecpar, pkt_queue, cb);
            worker->start();
            workers_.push_back(std::move(worker));
        }else if(codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE){
            auto subtitle_worker = std::make_unique<SubtitleDecoderWorker>(
                i, fmt_ctx_, pkt_queue, subtitle_cb_);
            subtitle_worker->start();
            subtitle_workers_.push_back(std::move(subtitle_worker));
        }
    }

    running_ = true;
    decode_thread_ = std::thread(&FrameDecoder::readLoop, this);
}

void FrameDecoder::stop() {
    running_ = false;
    // 🔁 等待读线程先退出
    if (decode_thread_.joinable()) decode_thread_.join();
    // 🧹 再关闭输入流
    if (fmt_ctx_) {
        avformat_close_input(&fmt_ctx_);
        fmt_ctx_ = nullptr;
    }
    // 停止所有解码线程
    for (auto& w : workers_) {
        w->stop();
    }
    workers_.clear();
    // 通知所有解码队列
    for (auto& [_, q] : pkt_queues_) {
        q->notifyAll();
        q->clear();
    }

}


void FrameDecoder::readLoop() {
    while (running_) {
        AVPacket* pkt = av_packet_alloc();
        if (av_read_frame(fmt_ctx_, pkt) < 0) {
            av_packet_free(&pkt);
            std::this_thread::sleep_for(std::chrono::milliseconds(5));
            continue;
        }

        int stream_index = pkt->stream_index;
        auto it = pkt_queues_.find(stream_index);
        if (it != pkt_queues_.end()) {
            it->second->push(pkt);
        } else {
            av_packet_free(&pkt);
        }
    }
}


}  // namespace WD
